package watch

import (
	"bufio"
	"fmt"
	"os"
	"reflect"
	"runtime"
	"strings"
	"time"
)

type Configuration map[string]string


type MyError struct{
	message string
	code int
}

var division byte//division确定注释的符号

/**
 * @api {get} /watch.go/MyInit() MyInit()
 * @apiGroup Init
 * @apiDescription 根据当前的运行环境，初始化注释的分隔符
 */
func myInit() {
	if runtime.GOOS == "windows"{
		division = ';'
	}else{
		division = '#'
	}
}

/**
 * @api {get} /watch.go/ Error()
 * @apiGroup MyError
 * @apiDescription 返回Myerror的error字符串
 */
func(err *MyError) Error() string{
	return err.message
}

/**
 * @api {get} /watch.go/ New()
 * @apiGroup MyError
 * @apiDescription 初始化错误
 * @apiParam {string} msg 错误的信息
 * @apiParam {int} cod 错误的种类
 */
func New(msg string,cod int) *MyError {
	return &MyError{
		message:msg,
		code:cod,
	}
}

//listener
type ListenFunc func(string)

type Listener interface {
	listen(inifile string)
}
/**
 * @api {get} /watch.go/ listen()
 * @apiGroup Listener
 * @apiDescription 返回Myerror的error字符串
 * @apiParam {string} inifile 输入的文件(文件路径)
 */
func (listenfunc ListenFunc) listen(inifile string){
	config,_ := ReadFile(inifile)
	fmt.Println("Begin to listen!")
	for{
		curConfig,_:=ReadFile(inifile)
		if !reflect.DeepEqual(config,curConfig){
			break
		}
		time.Sleep(2*time.Millisecond)
	}
}

/**
 * @api {get} /watch.go/ ReadFile()
 * @apiGroup File
 * @apiDescription 读取文件并返回ini的键值对和自定义错误类型
 *
 * @apiParam {string} filename 文件名称（路径）
 */
func ReadFile(filename string)(Configuration, *MyError){
	myInit()

	res := Configuration{}
	var myErr *MyError

	inputFile,err:= os.Open(filename)
	if err!=nil{
		myErr = New("fail to open the file",1)
		return res,myErr
	}else{
		myErr = New("",0)
	}

	defer  inputFile.Close()

	inputReader := bufio.NewReader(inputFile)

	for{
		inputString,err:=inputReader.ReadString('\n')
		if err!=nil{
			break
		}

		tempString := strings.Replace(inputString," ","",-1)
		tempString = strings.Replace(tempString,"\r","",-1)
		tempString = strings.Replace(tempString,"\n","",-1)

		if tempString == "" || tempString[0] == division || tempString[0] == '['{
			continue
		}

		words := strings.Split(tempString,"=")
		key := words[0]
		value :=words[1]
		res[key] = value
	}
	return res,myErr
}

/**
 * @api {get} /watch.go/ Watch()
 * @apiGroup File
 * @apiDescription 读取Ini文件中的配置信息，并且持续坚挺
 *
 * @apiParam {string} filename 文件名称（路径）
* @apiParam {Listener} listener 持续监听该文件的接口
 */
func Watch(filename string,listener Listener)(Configuration,*MyError){
	config,err := ReadFile(filename)
	if len(err.message) >0{
		fmt.Printf("error:%s\n errorCode: %d\n",err.Error(),err.code)
	}
	printConfig(config)
	listener.listen(filename)
	fmt.Println("The file has been changed")
	config,err = ReadFile(filename)
	if len(err.message)>0 {
		fmt.Printf("error:%s\n  errorCode: %d\n",err.Error(),err.code)
	}
	printConfig(config)
	return config,err
}

func printConfig(configure Configuration) {
	fmt.Printf("Print configure: \n")
	for key, value := range configure {
		fmt.Println(key, "=", value)
	}
}
